<template>
  <div class="form-wrappers">
    <el-form :model="resource" :rules="rules" ref="form" class="form-wrapper">
      <el-row class="syfm">
        <el-form-item prop="url" label="实验资源">
          <div
            class="drop-area el-upload-dragger"
            @click="clickElement($event, 'upload_folder')"
            @drop="handleFileDrop($event)"
            @dragleave="stopEvent($event)"
            @dragenter="stopEvent($event)"
            @dragover="stopEvent($event)"
          >
            <!-- <i class="el-icon-upload"></i> -->

            <img src="@/images/syzyicon.png" alt="" class="teximg" />

            <div class="el-upload__text">
              请将资源文件目录拖拽到此处,或点此添加
              <br />
              <!-- TODO 在方法中判断 -->
              <div class="scjd">
                <em v-if="allFileNum > 0 && allFileNum === upFileNum"
                  >已上传</em
                >
                <em v-if="allFileNum > 0 && allFileNum > upFileNum"
                  >正在上传：{{ upFileNum }}/{{ allFileNum }}</em
                >
              </div>
              <!-- <em v-if="!isModify && allFileNum == 0" style="color: #F56C6C;"
                >未上传, 请选择目录</em
              > -->
              <div
                class="zyscts"
                v-if="!allFileNum && isModify"
                v-html="resourceMessage"
              ></div>
              <input
                ref="upload_folder"
                webkitdirectory
                type="file"
                accept="*"
                style="display: none"
                @change="handleFileInput($event)"
              />
            </div>
          </div>
        </el-form-item>
        <el-form-item prop="cover" label="实验封面" class="drop-areas">
          <el-upload
            action="#"
            accept=".jpg, .png, .jpeg"
            :http-request="option => handleFileUpload(option, 'cover')"
            :before-upload="checkImageType"
            :show-file-list="false"
            class="drop-area el-upload-dragger"
          >
            <el-image
              v-if="resource.cover"
              :src="resource.cover"
              class="upload-content"
              fit="contain"
            ></el-image>
            <div v-else>
              <div v-if="coverFlag">
                <el-progress
                  type="circle"
                  :percentage="coverProgress"
                  style="margin: 25px 0 0 0 ;"
                ></el-progress>
              </div>
              <div v-else>
                <img src="@/images/syfmicon.png" alt="" class="teximg " />

                <div class="el-upload__text">请上传封面</div>
              </div>
            </div>
          </el-upload>
        </el-form-item>
      </el-row>
      <el-row class="symc">
        <el-form-item prop="name" label="实验名称">
          <el-input v-model="resource.name" class="sykdx" />
        </el-form-item>
        <el-form-item prop="code" label="实验标识" class="drop-areas">
          <el-input v-model="resource.code" class="sykdx" />
        </el-form-item>
      </el-row>
      <el-row class="symc">
        <el-form-item prop="deptId" label="组织机构">
          <el-select
            v-model="resource.deptId"
            placeholder="请选择组织机构"
            class="sykdx"
            @change="getDepUser"
          >
            <el-option
              v-for="item in depts"
              :key="item.id"
              :label="item.title"
              :value="item.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <!-- 回显接口得修改 userlistID 或者提交接口修改 -->
        <el-form-item prop="userList" label="联系人" class="drop-areass">
          <el-select
            v-model="resource.userList"
            collapse-tags
            placeholder="请选择联系人"
            class="sykdx"
            multiple
            @change="cs"
            ref="lianxi"
          >
            <el-option
              v-for="item in deptUsers"
              :key="item.userId"
              :label="item.name"
              :value="item.userId"
            ></el-option>
          </el-select>
        </el-form-item>
      </el-row>
      <el-row class="symc">
        <el-form-item prop="mode" label="实验模式">
          <el-select
            v-model="resource.mode"
            collapse-tags
            placeholder="请选择实验模式"
            class="sykdx"
          >
            <el-option
              v-for="item in modedata"
              :key="item.Id"
              :label="item.name"
              :value="item.Id"
            ></el-option>
          </el-select>
        </el-form-item>
      </el-row>
      <el-row>
        <el-form-item
          prop="introductionJson.content"
          label="实验简介"
          class="syjj"
        >
          <vue-editor
            id="editor"
            v-model="resource.introductionJson.content"
            :editorToolbar="editorToolbar"
          />
        </el-form-item>
      </el-row>
    </el-form>
  </div>
</template>

<script>
import { VueEditor } from 'vue2-editor'
import { createMultipartUpload, listObjects } from '@/utils/oss.js'
import {
  listResourceMode,
  listMajorByPid,
  checkCode
} from '@/api/simulation.js'
import { majorList } from '@/api/major.js'
import { deptList, deptUser } from '@/api/sysDept.js'
export default {
  components: {
    VueEditor
  },
  props: {
    resource: {
      type: Object,
      default: () => ({})
    },
    isModify: {
      type: Boolean,
      default: true
    }
  },
  watch: {
    resource: {
      handler(i) {
        this.$emit('update:resource', this.resource)
        console.log('检测到变化', i)
      },
      deep: true,
      immediate: true
    }
  },
  data() {
    const that = this
    const validateCode = (rule, value, callback) => {
      checkCode(value, that.resource.id || '').then(({ data }) => {
        callback(data ? undefined : new Error('实验标识已存在'))
      })
    }
    return {
      modedata: [
        {
          Id: 'old',
          name: '18旧版'
        },
        {
          Id: 'new',
          name: '22新版'
        },
        {
          Id: 'exam',
          name: '18考核'
        }
      ],
      userList: [],
      mode: '',
      modes: [], // 实验模式参数列表
      majors: [], // 专业参数列表
      types: [], // 类别参数列表
      isLock: false, // `isLock: true` 后可以上传文件, 禁止上传后修改路径
      objects: [],
      videoFlag: false,
      videoProgress: 0,
      coverFlag: false,
      coverProgress: 0,
      allFileNum: 0,
      upFileNum: 0,
      resourceMessage: '', // 资源上传框提示信息
      depts: [],
      deptUsers: [], //学生信息
      vrTypes: [
        {
          id: '国家申报',
          title: '国家申报'
        },
        {
          id: '定制化',
          title: '定制化'
        }
      ],

      // 表单校验
      rules: {
        name: [
          {
            required: true,
            message: '请输入实验名称',
            trigger: 'change'
          }
        ],
        code: [
          {
            required: true,
            message: '请输入实验标识',
            trigger: 'blur'
          },
          {
            required: true,
            validator: validateCode,
            trigger: 'blur'
          }
        ],
        version: [
          {
            required: true,
            message: '请输入版本号',
            trigger: 'blur'
          }
        ],
        introductionJson: {
          content: [
            {
              required: true,
              message: '请输入实验简介',
              trigger: 'blur'
            }
          ]
        },
        cover: [
          {
            required: true,
            message: '请上传实验封面',
            trigger: 'blur'
          }
        ],
        url: [
          {
            required: true,
            message: '请上传实验资源',
            trigger: 'blur'
          }
        ],
        mode: [
          {
            required: true,
            message: '请选择实验模式',
            trigger: 'blur'
          }
        ],
        // majorId: [
        //   {
        //     required: true,
        //     message: '请选择专业',
        //     trigger: 'change'
        //   }
        // ],
        deptId: [
          {
            required: true,
            message: '请选择所属组织机构',
            trigger: 'change'
          }
        ],
        userList: [
          {
            required: true,
            message: '请选择联系人',
            trigger: 'blur'
          }
        ],
        vrType: [
          {
            required: true,
            message: '请选择实验类别',
            trigger: 'change'
          }
        ],
        typeId: [
          {
            required: true,
            message: '请选择类别',
            trigger: 'change'
          }
        ]
      },
      // 富文本参数
      editorToolbar: [
        [
          {
            header: [false, 1, 2, 3, 4, 5, 6]
          },
          'bold',
          'italic',
          'underline',
          {
            align: ''
          },
          {
            align: 'center'
          },
          {
            align: 'right'
          }
        ],
        [
          {
            list: 'ordered'
          },
          {
            list: 'bullet'
          },
          {
            list: 'check'
          }
        ],
        [
          {
            background: []
          },
          {
            color: []
          }
        ],
        ['strike'],
        ['clean']
      ]
    }
  },
  created() {
    this.allFileNum = 0
    this.getDeptList()
    this.initForm()
    this.listResourceMode()
    this.getDepUser()
  },
  beforeDestroy() {
    // 页面关闭时重置上传相关数据
    this.allFileNum = 0
    this.upFileNum = 0
    this.objects = []
    this.isLock = false
    this.resourceMessage = ''
  },
  methods: {
    cs() {
      this.$forceUpdate()

      // 更新后手动验证
      // this.$nextTick(() => {
      //   this.$refs.form.validateField('userList') // 假设表单ref是form
      // })
      // console.log('选择了联系人', this.resource.userList)
    },
    getDepUser() {
      if (!this.resource.deptId) {
        return
      }
      this.resource.userList = []
      this.$set(this.resource, 'userList', [])
      deptUser(this.resource.deptId).then(async res => {
        this.deptUsers = res.data
        console.log(
          '查询了当前组织下的联系人',
          this.deptUsers,
          this.resource.userIdList,
          this.resource.userList
        )
        // this.resource.userList[0] = JSON.parse(
        //   JSON.stringify(this.resource.userIdList[0])
        // )

        if (this.deptUsers.length < 1) {
          this.resource.userList = []
        }
        if (!Array.isArray(this.resource.userList)) {
          this.$set(this.resource, 'userList', [])
        }
        if (this.resource.userIdList) {
          this.resource.userIdList.forEach(item => {
            this.resource.userList.push(item)
          })
          // this.$refs.lianxi.placeholder = '6666'
          const inputEl = this.$refs.lianxi.$el.querySelector(
            '.el-input__inner'
          )
          if (inputEl) {
            inputEl.placeholder = ''
          }
          this.$forceUpdate()
          // 赋值后手动触发表单校验，刷新 select 状态
          this.$nextTick(() => {
            this.$refs.form.validateField('userList')
          })

          console.log(
            '当前已绑定用户',
            this.resource.userList,
            this.$refs.lianxi.placeholder
          )
        } else {
          this.resource.userList = []
        }
      })
    },
    getDeptList() {
      deptList({}).then(async res => {
        this.depts = res.children
      })
    },
    // ==================== 文件上传 ====================
    /**
     * 图片 / 视频上传
     */
    handleFileUpload(option, attribute) {
      const { file } = option
      const suffix = file.name.slice(file.name.lastIndexOf('.'))
      const { majorId, typeId, code, version } = this.resource
      const key = `vrOrg/${majorId}/${typeId}/${code}/${version}/${attribute}/${this.createUUID()}${suffix}`
      createMultipartUpload(key, file, (progress, checkpoint) => {
        if (!checkpoint) {
          return
        }
        this[`${attribute}Flag`] = true
        this[`${attribute}Progress`] = Math.round(progress * 100)
      }).then(res => {
        const url = res.res.requestUrls[0]
        this.$set(
          this.resource,
          attribute,
          url.indexOf('?') === -1 ? url : url.slice(0, url.indexOf('?'))
        )
        this.videoFlag = false
        this.videoProgress = 0
        this.coverFlag = false
        this.coverProgress = 0
      })
    },
    checkSuccess() {
      this.allFileNum = this.objects.length
      this.upFileNum = this.objects.filter(
        item => item.uploading === false
      ).length
      if (this.allFileNum == this.upFileNum) {
        this.$refs['upload_folder'].value = ''
      }
    },
    /**
     * 资源文件上传
     * @param {File} file 本地文件
     * @param {String} relativePath 文件相对路径
     */
    handleResourceUpload(file, relativePath) {
      this.resource.attachPrefix = ''
      // 获取上传文件的文件名标识
      var a = relativePath.indexOf('/')
      var l = relativePath.substring(0, a)
      // this.resource.name = l
      // this.resource.code = l
      this.$set(this.resource, 'name', l)
      this.$set(this.resource, 'code', l)
      // 正式上传代码
      const that = this
      const { majorId, typeId, code, version } = this.resource
      const key = `vrOrg/${majorId}/${typeId}/${code}/${version}/${relativePath}`
      // 检查重复上传
      let index = this.objects.findIndex(item => item.key === key)
      if (index > -1) {
        this.objects[index].file = file
        return
      }
      // 上传
      this.objects.push({
        key: key,
        file: file,
        uploading: true
      })
      createMultipartUpload(key, file, this.multiUploadProgress).then(
        ({ name, res }) => {
          const target = that.objects.find(object => object.key === key)
          target.uploading = false
          // 更新lock状态
          that.checkSuccess()
          if (that.upFileNum === that.allFileNum) {
            that.$set(that, 'isLock', false)
          }
          // 通过任一 url 截取资源文件父目录, 通过 json 文件地址截取资源名称
          // url: http://zf-vr.oss-cn-hangzhou.aliyuncs.com/6/8/jyjb1/1.0.0/Build/MRWebGl.json
          const durl = /https?:\/\/[\w.:\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\/[\w.\-_%]*\//i
          const jurl = /[\w.:\-_\/%]*\/Build\/[\w.\-_%]*.json/i //旧版本
          const jurls = /[\w.:\-_\/%]*\/Build\/[\w.\-_%]*.data/i //新版本
          this.resource.url = res.requestUrls[0].match(durl)[0]

          console.log('上传完成返回1', res, this.mode)

          if (this.resource.mode == 'new') {
            console.log('上传完成返回newd', res, this.mode)
            if (name && name.match(jurls)) {
              const node = res.requestUrls[0].split('/')
              this.resource.attachPrefix = node[node.length - 1]
                .replace('.data', '')
                .split('?')[0]

              console.log('上传完成返回new32', this.resource.attachPrefix)
            }
          } else {
            if (name && name.match(jurl)) {
              const node = res.requestUrls[0].split('/')
              console.log('上传完成返回', this.resource.attachPrefix)
              this.resource.attachPrefix = node[node.length - 1].replace(
                '.json',
                ''
              )

              // console.log('上传完成返回', this.resource.attachPrefix)
            }
          }

          console.log('上传获取json', this.resource, this.resource.attachPrefix)

          // if (file.name == 'fm.png') {
          //   that.handleFileUpload(file, 'cover')
          //   // this.resource.cover =
          //   console.log('file.name', file.name)
          // }
        }
      )
    },
    /**
     * 分片上传进度
     * @param {Number} progress 分片上传进度, 取值范围: 0~1
     * @param {Object} checkpoint 本地分片上传结果
     */
    multiUploadProgress(progress, checkpoint) {
      if (!checkpoint) {
        return
      }
      const target = this.objects.find(item => item.key === checkpoint.name)
      this.$set(target, 'checkpoint', checkpoint)
      this.$set(target, 'progress', Math.round(progress * 100))
    },
    /**
     * 点击上传文件 / 目录
     */
    handleFileInput(event) {
      const that = this

      this.checkField()
        .then(() => {
          // 校验通过, 上传, 禁止修改
          this.isLock = true
          for (const file of event.target.files) {
            that.handleResourceUpload(
              file,
              file.webkitRelativePath || file.name
            )
            // console.log('判断文件类型是不是图片如果是判定为封面file', file.name)
          }
        })
        .catch(() => {
          // 不通过, 清空上传
          this.$refs['upload_folder'].value = ''
        })
    },
    /**
     * 拖拽上传文件 / 目录
     */
    handleFileDrop(event) {
      this.stopEvent(event)
      this.checkField()
        .then(() => {
          this.isLock = true
          const items = event.dataTransfer.items
          if (!items.length || items[0].kind !== 'file') return
          for (const item of items) {
            const entry = item.webkitGetAsEntry()
            this.loadChildFiles(entry, entry.name)
          }
        })
        .catch(() => {
          this.$refs['upload_folder'].value = ''
        })
      // console.log('执行文件上传', this.resource.name)
    },
    /**
     * 递归获取文件
     * @param {FileSystemEntry|FileSystemDirectoryEntry} entry 文件 / 目录
     * @param {String} relativePath 文件/目录相对路径
     */
    loadChildFiles(entry, relativePath) {
      // if (!this.resource.name && !this.resource.code) {
      //   var a = relativePath.indexOf('/')
      //   var l = relativePath.substring(0, a)
      //   this.resource.name = l
      //   this.resource.code = l
      // }

      const that = this
      if (entry.isFile) {
        entry.file(file => that.handleResourceUpload(file, relativePath))
        return
      }
      const reader = entry.createReader()
      reader.readEntries(entries =>
        entries.forEach(entry =>
          that.loadChildFiles(
            entry,
            `${relativePath ? relativePath : ''}/${entry.name}`
          )
        )
      )
    },
    // ==================== 页面动作 ====================
    /**
     * 初始化页面
     */
    initForm() {
      this.objects = []
      this.$set(this.resource, 'majorId', '1')
      this.$set(this.resource, 'typeId', '1')
      // 初始化 userList 为空数组（防止初始 undefined）
      // this.$set(this.resource, 'userList', [])
      this.checkOSSResource()
    },
    async checkOSSResource() {
      // 验证 OSS 文件目录存在
      const { res } = await listObjects(this.resource.url)
      this.resourceMessage =
        res.requestUrls && res.requestUrls.length
          ? `<em style="color: #67C23A">服务器存在本实验资源</em>`
          : '<em style="color: #F56C6C">资源已被删除, 需重新上传</em>'
      console.log(this.resourceMessage)
    },
    /**
     * 数据处理, 表单验证
     */
    beforeSubmit() {
      // if (!this.resource.attachPrefix) {
      //   this.$message('实验资源中无json文件')
      //   return false
      // }
      if (this.allFileNum > this.upFileNum) {
        this.$message('文件上传中')
        return false
      }
      const { content } = this.resource.introductionJson
      const text = content.replace(/<[^>]+>/g, '')
      this.resource.introduction = JSON.stringify({
        content,
        text
      })
      return new Promise((resolve, reject) => {
        this.$refs['form'].validate(valid => {
          if (!valid) {
            return false
          }
          resolve()
        })
      })
    },
    /**
     * 上传参数全部通过
     */
    checkField() {
      const that = this
      const filed = ['version', 'mode']
      //  const filed = ['code', 'version', 'mode']
      return new Promise((resolve, reject) => {
        let success = true
        that.$refs['form'].validateField(filed, error => {
          if (error) {
            success = false
          }
        })
        if (success) {
          resolve()
        } else {
          this.$refs['upload_folder'].value = ''
          this.$message.error('请检查上传必要参数')
        }
      })
    },
    resetForm() {
      this.$refs['form'].resetFields()
      this.deptUsers = null
    },
    // ==================== 参数列表 ====================
    /**
     * 选择专业重置类型
     */
    resetType() {
      this.$set(this.resource, 'typeId', null)
      this.listType()
    },
    /**
     * 实验资源使用模式
     */
    listResourceMode() {
      listResourceMode().then(({ code, msg, data }) => {
        this.modes = data
      })
    },
    /**
     * 专业查询
     */
    listMajor() {
      majorList({}).then(res => {
        this.majors = res.children
      })
    },
    /**
     * 类型查询
     */
    listType() {
      listMajorByPid(this.resource.majorId).then(({ code, msg, data }) => {
        this.types = data
      })
    },
    // ==================== utils ====================
    /**
     * 图片格式验证
     */
    checkImageType({ type }) {
      const isPic = type.startsWith('image')
      if (!isPic) {
        this.$message.error('封面必须是 图片！')
      }
      return isPic
    },
    /**
     * 视频格式验证
     */
    checkVideoType({ type }) {
      const isVideo = type.startsWith('video')
      if (!isVideo) {
        this.$message.error('演示必须是 视频！')
      }
      return isVideo
    },
    /**
     * 阻止浏览器默认操作
     */
    stopEvent(event) {
      event.stopPropagation()
      event.preventDefault()
    },
    /**
     * 模拟点击
     */
    clickElement(event, el) {
      event.stopPropagation()
      this.$refs[el].click()
    },
    /**
     * 随机串
     */
    createUUID() {
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
        let r = (Math.random() * 16) | 0,
          v = c == 'x' ? r : (r & 0x3) | 0x8
        return v.toString(16)
      })
    }
  }
}
</script>
<style scoped>
.el-form-item {
  display: flex !important;
}
.drop-area {
  width: 359px;
  height: 143px;
  /* line-height: 143px; */
}
.drop-areas {
  margin-left: 50px;
}
.drop-areass {
  margin-left: 64px;
}
.syfm {
  display: flex;
}
.el-form-item--medium .el-form-item__content {
  line-height: 0px !important;
}
.teximg {
  margin-top: 25px;
}
.symc {
  display: flex;
}
.zyscts {
  margin-top: -13px;
}
.scjd {
  margin-top: -13px;
}
</style>
